package com.youlu.campus.web.config;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.youlu.campus.base.base.Constants;
import com.youlu.campus.base.exception.AccountException;
import com.youlu.campus.base.exception.AuthException;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.exception.CaReceiveNotFoundException;
import com.youlu.campus.base.exception.CommonException;
import com.youlu.campus.base.exception.DuplicateOrderException;
import com.youlu.campus.base.exception.EnglishMobileReceiveException;
import com.youlu.campus.base.exception.EnglishReceiveCaException;
import com.youlu.campus.base.exception.InvalidRequestParamException;
import com.youlu.campus.base.exception.MobileUserException;
import com.youlu.campus.base.exception.MobileUserNotFoundException;
import com.youlu.campus.base.exception.NameAndUniversityException;
import com.youlu.campus.base.exception.NotExistCertificateException;
import com.youlu.campus.base.exception.PointReceiveCertificateException;
import com.youlu.campus.base.exception.QaMaxLimitException;
import com.youlu.campus.base.exception.UserNotFoundException;
import com.youlu.campus.base.exception.UserPointException;
import com.youlu.campus.common.exception.WechatException;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;

import java.util.Map;

/**
 * 异常处理切面
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(InvalidRequestParamException.class)
    public Object handleInvalidRequestParamException(InvalidRequestParamException e) {
        log.error("InvalidRequestParamException：{}", e.getMessage(), e);
        return QResult.fail(400, e.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Object handleServiceException(BusinessException e) {
        log.error("BusinessException：{}", e.getMessage(), e);
        int code = 500;
        try {
            if (StringUtils.isNotBlank(e.getMessage())) {
                if (e.getMessage().indexOf(Constants.EXCEPTION_MESSAGE_CODE_SEPARATOR) > 0) {
                    code = Integer.valueOf(e.getMessage().split(Constants.EXCEPTION_MESSAGE_CODE_SEPARATOR)[1]);
                }
            }
        } catch (Exception ex) {
            //nothing to do
        }
        return QResult.fail(code, e.getMessage());
    }

    @ExceptionHandler(com.youlu.campus.common.exception.BusinessException.class)
    public Object handleServiceException(com.youlu.campus.common.exception.BusinessException e) {
        log.error("BusinessException：{}", e.getMessage(), e);
        int code = 500;
        try {
            if (StringUtils.isNotBlank(e.getMessage())) {
                if (e.getMessage().indexOf(Constants.EXCEPTION_MESSAGE_CODE_SEPARATOR) > 0) {
                    code = Integer.valueOf(e.getMessage().split(Constants.EXCEPTION_MESSAGE_CODE_SEPARATOR)[1]);
                }
            }
        } catch (Exception ex) {
            //nothing to do
        }
        return QResult.fail(code, e.getMessage());
    }

    @ExceptionHandler(AccountException.class)
    public Object handleServiceException(AccountException e) {
        log.error("AccountException：{}", e.getMessage(), e);
        return QResult.fail(500, e.getMessage());
    }

    @ExceptionHandler(WechatException.class)
    public Object handleWechatException(WechatException e) {
        log.error("WechatException：{}", e.getMessage(), e);
        return QResult.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(CommonException.class)
    public Object handleCommonException(CommonException e) {
        log.error("CommonException：{}", e.getMessage(), e);
        return QResult.fail(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(AuthException.class)
    public Object handleAuthException(AuthException e) {
        log.error("AuthException：{}", e.getMessage(), e);
        return QResult.fail(5, e.getMessage());
    }

    @ExceptionHandler(MultipartException.class)
    public Object handleError1(MultipartException e) {
        log.error("MultipartException：{}", e.getMessage(), e);
        return QResult.fail(500, "文件处理异常！");

    }

    @ExceptionHandler(FileUploadBase.FileSizeLimitExceededException.class)
    public Object handleError2(FileUploadBase.FileSizeLimitExceededException e) {
        log.error("FileSizeLimitExceededException：{}", e.getMessage(), e);
        return QResult.fail(500, "上传文件过大,请重新上传！");

    }

    @ExceptionHandler(IllegalArgumentException.class)
    private Object illegalArgumentExceptionHandler(IllegalArgumentException e) {
        log.error("IllegalArgumentException：{}", e.getMessage(), e);
        return QResult.fail(500, e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    private Object illegalParamsExceptionHandler(MethodArgumentNotValidException ex) {
        log.error("MethodArgumentNotValidException：{}", ex.getMessage(), ex);
        BindingResult bindingResult = ex.getBindingResult();
        Map<String, String> errors = Maps.newHashMapWithExpectedSize(bindingResult.getFieldErrorCount());
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
            log.warn("---------> invalid request! fields ex:{}", JSON.toJSONString(errors));
            return QResult.fail(500, fieldError.getDefaultMessage());
        }
        return QResult.fail(500, "系统异常:请联系客服!");
    }

    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
        log.error("Exception：{}", e.getMessage(), e);
        return QResult.fail(500, "系统未知异常,请联系客服或管理员");
    }

    @ExceptionHandler(UserNotFoundException.class)
    public Object handleUserNotFoundException(UserNotFoundException e) {
        log.error(">>>>>>>用户通过openid找不到,异常信息：{}", e.getMessage(), e);
        return QResult.fail(50001, e.getMessage());
    }

    @ExceptionHandler(MobileUserNotFoundException.class)
    public Object handleMobileUserNotFoundException(MobileUserNotFoundException e) {
        log.error(">>>>>>>用户通过【手机号】找不到,异常信息：{}", e.getMessage(), e);
        return QResult.fail(50002, e.getMessage());
    }


    @ExceptionHandler(MobileUserException.class)
    public Object handleMobileUserException(MobileUserException e) {
        log.error(">>>>>>>用户通过【手机号】验证,异常信息：{}", e.getMessage(), e);
        return QResult.fail(50003, e.getMessage());
    }

    @ExceptionHandler(EnglishReceiveCaException.class)
    public Object handleEnglishException(EnglishReceiveCaException e) {
        log.error(">>>>>>>【英语竞赛】用户领取电子证书,异常信息：{}", e.getMessage(), e);
        return QResult.fail(50005, e.getMessage());
    }

    @ExceptionHandler(EnglishMobileReceiveException.class)
    public Object handleEnglishMobileException(EnglishMobileReceiveException e) {
        log.error(">>>>>>>【英语竞赛】用户手机号领取,异常信息：{}", e.getMessage(), e);
        return QResult.fail(50004, e.getMessage());
    }

    @ExceptionHandler(QaMaxLimitException.class)
    public Object handleQaException(QaMaxLimitException e) {
        log.error(">>>>>>>【答题】答题超：{}", e.getMessage(), e);
        return QResult.fail(50010, e.getMessage());
    }

    @ExceptionHandler(CaReceiveNotFoundException.class)
    public Object handleCaReceiveNotFoundException(CaReceiveNotFoundException e) {
        log.error(">>>>>>>【答题】答题超：{}", e.getMessage(), e);
        return QResult.fail(50011, e.getMessage());
    }

    @ExceptionHandler(UserPointException.class)
    public Object handleUserPointException(UserPointException e) {
        log.error(">>>>>>>【用户积分不足】领取电子证书：{}", e.getMessage(), e);
        return QResult.fail(50012, e.getMessage());
    }

    @ExceptionHandler(NameAndUniversityException.class)
    public Object handleNameAndUniversityException(NameAndUniversityException e) {
        log.error(">>>>>>>【报名信息姓名、学校未空】领取电子证书：{}", e.getMessage(), e);
        return QResult.fail(50013, e.getMessage());
    }


    @ExceptionHandler(NotExistCertificateException.class)
    public Object handleNotExistCertificateException(NotExistCertificateException e) {
        log.error(">>>>>>>领取电子证书不存在：{}", e.getMessage(), e);
        return QResult.fail(6000, e.getMessage());
    }


    @ExceptionHandler(PointReceiveCertificateException.class)
    public Object handlePointReceiveCertificateException(PointReceiveCertificateException e) {
        log.error(">>>>>>>领取电子证书积分不足：{}", e.getMessage(), e);
        return QResult.fail(6001, e.getMessage());
    }

    @ExceptionHandler(DuplicateOrderException.class)
    public Object handleDuplicateOrderException(DuplicateOrderException e) {
        log.error(">>>>>>>重复订单异常：{}", e.getMessage(), e);
        return QResult.fail(7000, e.getMessage());
    }

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public Object uploadFileException(MaxUploadSizeExceededException e) {
        log.error(">>>>>>>上传文件过大,异常信息：{}", e.getMessage(), e);
        return QResult.fail(500, "上传文件太大,请上传文件不超过10M");
    }

}
